package lineareListen;

public class Liste
{
    private ListElement kopf;

    private ListElement aktuell;

    private ListElement vorgaenger;

    boolean istLeer()
    {
        return kopf == null;
    }

    void durchlaufe()
    {
        if (!(istLeer()))
        {
            ListElement current = kopf;
            while (current != null)
            {
                System.out.println(current.getDaten() + " ");
                current = current.getNaechstes();
            }
        }
        else
        {
            System.out.println("Liste ist leer!");
        }
    }

    boolean finde(Object einObject)
    {
        vorgaenger = null;
        aktuell = kopf;
        while (aktuell != null)
        {
            if (einObject.equals(aktuell.getDaten()))
            {
                return true;
            }
            else
            {
                vorgaenger = aktuell;
                aktuell = aktuell.getNaechstes();
            }
        }
        return false;
    }

    Object getAktuelleDaten()
    {
        // Aktuelles Element muss vorhanden sein
        if (aktuell == null)
        {
            throw new NullPointerException("kein aktuelles Element");
        }
        return aktuell.getDaten();
    }

    void einfuegeHinter(Object neuesObject)
    {
        if (aktuell == null)
        {
            throw new NullPointerException();
        }
        ListElement neu = new ListElement(neuesObject, aktuell.getNaechstes());
        aktuell.setNaechstes(neu);
    }

    void einfuegeKopf(Object neuesObject)
    {
        ListElement neu = new ListElement(neuesObject, kopf);
        kopf = neu;
    }

    void einfuegeVor(Object neuesObject)
    {
        if (aktuell == null)
        {
            throw new NullPointerException();
        }
        ListElement neu = new ListElement(neuesObject, aktuell);
        if (vorgaenger == null)
        {
            kopf = neu;
        }
        else
        {
            vorgaenger.setNaechstes(neu);
        }
    }

    void einfuegeVorSicher(Object neuesObject)
    {
        if (aktuell == null)
        {
            throw new NullPointerException();
        }
        if (aktuell == kopf)
        {
            einfuegeKopf(neuesObject);
            return;
        }
        ListElement vorgaenger = kopf; // Suche Vorgaenger
        while (vorgaenger.getNaechstes() != aktuell)
        {
            vorgaenger = vorgaenger.getNaechstes();
        }
        ListElement neu = new ListElement(neuesObject, aktuell);
        vorgaenger.setNaechstes(neu);
    }

    void loescheNachfolger()
    {
        // aktuell muss vorhanden sein
        if (aktuell == null)
        {
            throw new NullPointerException("loescheNachfolger: kein aktuelles Element");
        }
        // Nachfolger von aktuell muss vorhanden sein
        if (aktuell.getNaechstes() == null)
        {
            throw new NullPointerException("loescheNachfolger: kein Nachfolger");
        }
        aktuell.setNaechstes(aktuell.getNaechstes().getNaechstes());
    }

    void loescheElement()
    {
        if (aktuell.getNaechstes() == null)
        {
            throw new NullPointerException();
        }
        if (vorgaenger == null)
        {
            kopf = aktuell.getNaechstes();
        }
        else
        {
            vorgaenger.setNaechstes(aktuell.getNaechstes());
        }
    }

    int zaehleElemente()
    {
        int zaehler = 0;
        aktuell = kopf;
        if (!(istLeer()))
        {
            while (aktuell != null)
            {
                vorgaenger = aktuell;
                aktuell = aktuell.getNaechstes();
                zaehler++;
            }
        }

        return zaehler;
    }

    void findeEnde()
    {
        aktuell = kopf;
        if (istLeer())
        {
            return;
        }
        while (aktuell.getNaechstes() != null)
        {
            vorgaenger = aktuell;
            aktuell = aktuell.getNaechstes();
        }
    }

    Object getKopfDaten()
    {
        if (kopf == null)
        {
            throw new NullPointerException("kein Kopf");
        }
        return kopf.getDaten();
    }

    Object getEndeDaten()
    {
        findeEnde();
        return getAktuelleDaten();
    }

    void einfuegeEnde(Object neuesObject)
    {
        if (istLeer())
        {
            einfuegeKopf(neuesObject);
        }
        else
        {
            ListElement neu = new ListElement(neuesObject, null);
            if (neuesObject != null)
            {
                findeEnde();
                aktuell.setNaechstes(neu);
            }
        }
    }

    void loescheKopf()
    {
        if (istLeer())
        {
            throw new NullPointerException("Liste ist leer!");
        }
        else
        {
            kopf = kopf.getNaechstes();
        }
    }

    void loescheEnde()
    {
        aktuell = kopf;
        if (!(istLeer()))
        {
            if (kopf.getNaechstes() != null)
            {
                findeEnde();
                vorgaenger.setNaechstes(null);
            }
            else
            {
                loescheKopf();
            }
        }
    }

    void konkatenieren(Liste l)
    {
        findeEnde();
        if (aktuell == null)
        {
            kopf = l.kopf;
        }
        else
        {
            aktuell.setNaechstes(l.kopf);
        }
    }

    void spiegeln()
    {
        // Liste spiegel = new Liste();
        // ListElement tmp = kopf;
        // while (tmp != null)
        // {
        // spiegel.einfuegeKopf(tmp.getDaten());
        // tmp = tmp.getNaechstes();
        // }
        // kopf = spiegel.kopf;

        vorgaenger = null;
        aktuell = kopf;

        if (aktuell == null)
        {
            return;
        }
        if (aktuell.getNaechstes() == null)
        {
            return;
        }

        while (aktuell != null)
        {
            ListElement naechstes = aktuell.getNaechstes();
            aktuell.setNaechstes(vorgaenger);
            vorgaenger = aktuell;
            aktuell = naechstes;
        }
        // vorgaenger verweist jetzt auf den letzten Knoten der
        // Original-Liste, also auf den Kopf der gespiegelten Liste
        kopf = vorgaenger;

    }

    boolean vergleiche(Liste l)
    {
        if (istLeer() && l.istLeer())
        {
            return true;
        }
        if ((zaehleElemente() == l.zaehleElemente()))
        {

            aktuell = kopf;
            l.aktuell = l.kopf;
            while (aktuell != null)
            {
                if (!(aktuell.getDaten().equals(l.aktuell.getDaten())))
                {
                    return false;
                }
                aktuell = aktuell.getNaechstes();
                l.aktuell = l.aktuell.getNaechstes();
            }
            return true;
        }
        return false;
    }

}
